/**
 * @file    Renderer.java
 * @author  Lobsang Alvites Szaler <l.alvites@lpcsite.com>
 * @date    24 Jul 2007
 * @version 1.0
 *
 */

package sim.framework;

import java.io.*;
import java.util.Vector;
import sim.utils.*;

import sim.framework.*;
import sim.framework.gui.*;


public class Renderer extends Thread {
    
    public static final int TICK_MS = 50;
    
    private static final int LOCKED_FOR_SET = 1;
    private static final int LOCKED_FOR_RENDERER = 2;

    private Simlet m_Simlet;    
    private Gui m_Gui = null;
    private boolean m_bQuit = false;

    public Renderer(Simlet s) {
	m_Simlet = s;
    }
    
    public void run() {
        long period = 0;
        
	while( !m_bQuit ) {

	    try {
		period = renderer();
	    }
	    catch (Exception e) {
		System.out.println("\nME CAI EN RENDERER\n");
		System.out.println("\nMesage\n");
		e.getMessage();
		System.out.println("\nTrace\n");
		e.printStackTrace();		   
	    }

	    synchronized(this) {
		try {
		    if (period >= 0) {
			wait(period);
		    }
		} catch(InterruptedException e ) {
		    
		}
	    }
	}
    }
    
    private synchronized long lock(int lockFor, Gui gui) {
	long ret = 0;
	switch (lockFor) {
	case LOCKED_FOR_SET:
	    lockedForSet(gui);
	    break;
	case LOCKED_FOR_RENDERER:
	    ret = lockedForRenderer();
	    break;
	}
	return ret;
    }

    private long lockedForSet(Gui gui) {
	m_Gui = gui;
	notify();
        return 0;
    }

    private long lockedForRenderer() {
        long initTime;
        long currTime;
	long period;
	
	//#ifdef DEBUG_RENDERER
	//# System.out.println("Renderer::lockedForRenderer() ENTERED");
	//#endif
	
	// Por defecto, domir por siempre si no hay GUI.
	period = 0;
	
	// Si ha un Gui estalecido ...
	if (m_Gui != null) {
	    // llamar a la renderización
	    initTime = System.currentTimeMillis();
	    period = m_Gui.renderer();
	    currTime = System.currentTimeMillis();
	    // Calcular el tiempo a dormir antes de llamar nuevamente a renderer.
	    if (period > 0) {
		period -= (currTime - initTime);
	    }
	}

	//#ifdef DEBUG_RENDERER
	//# System.out.println("Renderer::lockedForRenderer() EXITING");
	//#endif

	return period;
    }

    protected void set(Gui gui) {
	lock(LOCKED_FOR_SET, gui);
    }
    
    private long renderer() {
	return lock(LOCKED_FOR_RENDERER, null);
    }

    protected synchronized void stop(){
        m_bQuit = true;
	notify();
    }
}
